package ejb;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import util.XMLReader;
import bean.ArtPendiente;
import bean.ArtPendiente.EstadoEnvio;
import bean.Articulo;
import bean.PendienteFabricacion;
import ejbInterfaces.AdministradorRepAFBeanLocal;
import generated.RepAF;
import generated.RepAF.Articulos.ArticuloFabrica;

/**
 * Session Bean implementation class AdministradorRepAFBean
 */
@Stateless
public class AdministradorRepAFBean implements AdministradorRepAFBeanLocal {

	/**
	 * Default constructor.
	 */

	@PersistenceContext(unitName = "MyDatabase")
	EntityManager em;
	
	static Logger logger = Logger.getLogger(AdministradorRepAFBean.class);

	public AdministradorRepAFBean() {
		// TODO Auto-generated constructor stub
	}

	public List<Articulo> obtenerArticulosRecibidos() {
		RepAF repAF = XMLReader.getInstance().leerRepAF();
		List<Articulo> recibidos = new ArrayList<Articulo>();
		List<ArticuloFabrica> temp = repAF.getArticulos().getArticuloFabrica();
		try {
			for (ArticuloFabrica recibido : temp) {
				Query q = em.createQuery("from Articulo where referencia = ?1");
				q.setParameter(1, recibido.getRef());
				List<Articulo> result = q.getResultList();
				Articulo articulo = null;
				if (result.size() != 0) {
					articulo = result.get(0);
				}
				if (articulo != null) {
					// Actualizo Stock real
					actualizarPendienteFabricacion(recibido);
					articulo.setStock(articulo.getStock() + recibido.getCant());
					em.merge(articulo);
					recibidos.add(articulo);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.log(Level.ERROR, "Error obteniendo Reposicion", e);
		}

		return recibidos;
	}

	public List<ArtPendiente> obtenerArticulosPendientesEnvio(
			List<Articulo> recibidos) {
		List<ArtPendiente> listaPendientes = new ArrayList<ArtPendiente>();

		for (Articulo a : recibidos) {
			Query query = em
					.createQuery("from ArtPendiente where estado = :estado");
			query.setParameter("estado", EstadoEnvio.PENDIENTE);
			List<ArtPendiente> result = query.getResultList();
			if (result.size() != 0) {
				for (ArtPendiente r : result) {
					if (existe(r, recibidos) && !agregado(r, listaPendientes)) {
						listaPendientes.add(r);
					}
				}
			}
		}
		return listaPendientes;
	}

	// hago de esta manera solo para optimizar con una consulta a la BD
	// existe en la lista de articulos
	private boolean existe(ArtPendiente r, List<Articulo> recibidos) {
		boolean ret = false;
		for (Articulo a : recibidos) {
			if (a.getReferencia() == r.getReferencia()) {
				ret = true;
			}
			if (ret == true) {
				break;
			}
		}
		return ret;
	}

	private boolean agregado(ArtPendiente r, List<ArtPendiente> pendientes) {
		boolean ret = false;
		for (ArtPendiente p : pendientes) {
			if (p.getId() == r.getId() && p.getIdTienda() == r.getIdTienda()
					&& p.getNumSolDist() == r.getNumSolDist()) {
				ret = true;
				break;
			}

		}
		return ret;
	}

	private void actualizarArticulo(List<Articulo> articulos) {
		for (Articulo a : articulos) {
			Query q = em
					.createQuery("from Articulo where referencia = :ref");
			q.setParameter("ref", a.getReferencia());
			List<Articulo> result = q.getResultList();
			if (result.size() != 0) {
				Articulo art = result.get(0);
				if (art != null) {
					art.setStock(a.getStock());
					em.merge(art);
				} else {
					logger.log(Level.INFO, "El Articulo no existe");
					System.out.println("El Articulo no existe");
				}
			}
		}

	}

	private void actualizarPendientes(List<ArtPendiente> pendientes) {
		for (ArtPendiente p : pendientes) {
			ArtPendiente art = em.find(ArtPendiente.class, p.getId());
			// solo si la cantidad alcanza, > por las dudas
			if (art != null) {
				if (p.getCantidad() >= art.getCantidad()) {
					p.setEstado(EstadoEnvio.LISTO);
					em.merge(p);
				}
			} else {
				logger.log(Level.INFO, "El Articulo no existe");
				System.out.println("El Articulo no existe");
			}
		}
	}

	private void actualizarPendienteFabricacion(ArticuloFabrica a) {
		Query q = em
				.createQuery("from PendienteFabricacion where referencia = :ref");
		q.setParameter("ref", a.getRef());
		List<PendienteFabricacion> result = q.getResultList();
		if (result.size() != 0) {
			PendienteFabricacion p = result.get(0);
			int cant = p.getCantPendiente();
			cant = cant - a.getCant();
			if (cant < 0) {
				cant = 0;
			}
			if (cant == 0) {
				em.remove(p);
			} else {
				p.setCantPendiente(cant);
				em.merge(p);
			}
		}
	}

	public void actualizarPedidos(List<Articulo> articulos,
			List<ArtPendiente> pendientes) {
		actualizarArticulo(articulos);
		actualizarPendientes(pendientes);
		
	}

}
